home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume14 / mush6.0 / part06 < prev    next >
Encoding:
Internet Message Format  |  1988-04-12  |  45.4 KB

  1. From: island!argv@sun.com (Dan Heller)
  2. Subject: Mail User's Shell, version 6.0
  3.  
  4. #! /bin/sh
  5. # This is a shell archive.  Remove anything before this line, then unpack
  6. # it by saving it into a file and typing "sh file".  To overwrite existing
  7. # files, type "sh file -c".  You can also feed this as standard input via
  8. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  9. # will see the following message at the end:
  10. #        "End of archive 6 (of 14)."
  11. # Contents:  cmd_help fkeys.c select.c
  12. # Wrapped by rsalz@fig.bbn.com on Wed Apr 13 20:04:47 1988
  13. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  14. if test -f 'cmd_help' -a "${1}" != "-c" ; then 
  15.   echo shar: Will not clobber existing file \"'cmd_help'\"
  16. else
  17. echo shar: Extracting \"'cmd_help'\" \(16430 characters\)
  18. sed "s/^X//" >'cmd_help' <<'END_OF_FILE'
  19. X/* @(#)cmd_help    1.4    10/28/86 (Dan heller) */
  20. X
  21. X%?%
  22. The `?' will give you a list of legal commands.  Most commands
  23. accept -? as an option.  This will give you specialized help
  24. with that particular command.
  25. X%%
  26. X
  27. X%ignore%
  28. usage: ignore/unignore [headers]
  29. Use this command to set the message headers you would like not
  30. to be printed when you read a message. If no header specified,
  31. then a list of all headers currently being ignored is printed.
  32. You must specify a header for unignore.
  33. X
  34. You can set the variable "alwaysignore" to force normally
  35. ignored headers to be ignored while saving messages, forwarding
  36. messages or including messages into message buffers.
  37. X%%
  38. X
  39. X%set%
  40. usage: set/unset [variable] [= value]
  41. set by itself prints values for variables in its group
  42. To set a boolean variable (on or off), "set variable"
  43. To set a variable's value to a string, use:
  44. set variable = 'value'
  45. X
  46. If you want double-quote's or white-space embedded in
  47. a string, encase the string in single quotes.  If you
  48. want single quotes in a string, encase the string in
  49. double quotes.
  50. X
  51. Type "set ?all" for a list of all settable variables.
  52. X"set ?variable_name" for help on a single variable.
  53. X%%
  54. X
  55. X%readmsg%
  56. You can read messages in different ways.  "type" and "print"
  57. will print the current message.  "top" will only print the
  58. first N lines of the current message where N is the value of
  59. the variable "crt".  "next" will go to the next unread message
  60. and print that. "previous" will go back and read the first
  61. unread message previous to the current. ^ will print the first
  62. message, $ will print the last.
  63. All can be followed by a message list and each message in
  64. that list will be printed (or piped to other commands).
  65. X%%
  66. X
  67. X%alts_help%
  68. usage: alts [hostnames]
  69. alts contains a list of hostnames on which you have an account
  70. Normally, when you respond to all recipients of mail, your
  71. account name will be listed and you send yourself mail. If you
  72. don't have metoo set, then your name will be removed from the
  73. mailing list if your login name is on the list and the host
  74. specified is in the alternates list.  `*' matches all hostnames
  75. and only the login name is tested.
  76. X%%
  77. X
  78. X%source_help%
  79. usage: source/saveopts [file]
  80. source/saveopts will load/save all variable settings, options,
  81. aliases, cmd's, ignored headers ... everything you can set,
  82. it loads or saves. The file named used follows these rules:
  83. X
  84. X1) if a filename is given, that file is used.
  85. X2) file described by the environment variable MAILRC
  86. X3) user's home directory: .mailrc
  87. X%%
  88. X
  89. X%general%
  90. This is the general help message. To get help on a specific
  91. command, try "command -?". Extended help is given by typing
  92. X`help item' where item is one of:
  93. X    path, msg_list, prompt, hdr_format.
  94. Help with msg_list is highly advisable!
  95. X
  96. Type "?" to get a list of available commands.  Try "? command"
  97. to get help on the particular command that you specify.
  98. X%%
  99. X
  100. X%path%
  101. Whenever "path" is specified, the following syntax is legal besides the
  102. normal path addressing scheme used by unix.
  103. X~[user]     -- the home directory of specified user (yours by default)
  104. X%[user]     --/usr/spool/mail/login_name [user_name] (yours by default)
  105. X+file       --the directory described by `set folder'; file is `file'
  106. X%%
  107. X
  108. X%msg_list%
  109. A "msg_list" references one or more messages.  The user specifies
  110. a group of messages according to a special syntax.
  111. X
  112. X*      All messages.
  113. X^      The first message.
  114. X$      The last message.
  115. X.      The current message.
  116. N-M    A range of messages between N and M.
  117. X
  118. In the last case, N and M may be * ^ $ . or digits referencing
  119. explicit message numbers.  The range must be in ascending order.
  120. X
  121. You can also negate messages by placing the message list inside
  122. braces, `{' `}' -- thus, the expression "2-19 {11-14}" references
  123. messages 2 through 19 except for those between 11 through 14.
  124. X
  125. Commands can be "piped" to one another, because the return
  126. value of a command is a msg_list, not text.
  127. pick -f fred | lpr   will find all messages "from fred" and
  128. send them to the printer.
  129. X
  130. Commands dealing with more than one message process them in
  131. order -- not necessarily the order specified.  Thus, the command,
  132. save 1-5 9 7 6 file
  133. will save the messages in ascending order; not as specified.
  134. X%%
  135. X
  136. X%preserve_help%
  137. usage: preserve [msg_list]
  138. Preserve saves deleted or read messages in your mailbox.
  139. Without explicitely setting preserve, all mail that you
  140. read will be saved in ~/mbox (or set mbox).  If you set
  141. X"hold", then this is equivalent to preserving each message
  142. as you read it.
  143. X%%
  144. X
  145. X%save_help%
  146. usage: save/write/copy [!] [msg_list] [filename]
  147. X
  148. If no filename is specified, ~/mbox (or set mbox) is used.
  149. Save and write will append msg if `file' already exists
  150. Specifying the `!' will overwrite file (e.g. erasing it first).
  151. To save messages to a filename beginning with a digit,
  152. escape the filename with a backslash (\)
  153. X`write' will write message without the headers (msg body only).
  154. Save and write both mark messages for deletion unless "keepsave"
  155. is set.  Copy is identical to save except that messages are not
  156. marked for deletion (identical to having keepsave set).
  157. X%%
  158. X
  159. X%lpr%
  160. use: lpr [-n] [-h] [msg_list]
  161. X  -n         print body of message only (not headers)
  162. X  -h         print all headers with message body (default true)
  163. X  -Pxx       print on printer xx
  164. X%%
  165. X
  166. X%respond_help%
  167. usage: replysender/replyall [msg_list] [mail_flags] [users]
  168. Replysender only replies to the sender and replyall responds
  169. to everyone on the To: and Cc: lines of the message.
  170. X
  171. The commands "repond", "reply", and "r" are identical to
  172. X"replysender." The command, "R" is identical to "replyall."
  173. X
  174. If a message list is indicated, then each message on the list is
  175. replied to in the same manner.  All other arguments are passed
  176. to the mail command ('mail_flags' and 'users').
  177. X
  178. Type "mail -?" for information on legal mail flags.
  179. X%%
  180. X
  181. X%sort_help%
  182. usage: sort [-] [d | a | s | S | R]
  183. X  d         sort according to date received
  184. X  a         author (alphabetical)
  185. X  s         subject ignoring Re: as part of the subject
  186. X  R         subject (alphabetical)
  187. X  S         by status
  188. The optional `-' flag will reverse the order of sorting
  189. By default (no arguments), sort sorts messages by status:
  190. New, unread messages are first, followed by preserved messages
  191. and finally the deleted messages are placed at the end
  192. X%%
  193. X
  194. X%pick%
  195. use: pick [-r msg_list] [-d [-][date] ] [-s|f|t]] [-x] [-i] [-h hdr] [<pat>]
  196. Search for patterns within messages. Entire messages are searched
  197. for <pattern> unless -s, -f, -t, or -h is specified.
  198. Only one of -s, -f, -t, -d and -h can be specified at once.
  199. X-r msg_list  restrict the range of messages search to msg_list
  200. X-d: print message headers on or after [`-' before] `date' (no patterns).
  201. X-h hdr   requires a header to be searched for.  Pattern searched in that hdr.
  202. X     `date' is of the form: month/date/year
  203. X      Omitted fields default to today's values. Examples:
  204. X      pick -d 4/20     msgs on or after Apr 20, this year
  205. X      pick -d -/2/85   on or before the 2nd, this month, 1985
  206. X      pick -d /        finds today's messages only.
  207. X    At least one `/' char must be used in date.
  208. X    There is no strong date checking; 2/30 would be considered valid
  209. X-s search for pattern in the "subject" headers only.
  210. X-f search for pattern in the "from" field (author) only.
  211. X-t search for pattern in the "to" field.
  212. X-i ignore case of letters.
  213. X-x return those messages which do NOT match.
  214. X%%
  215. X
  216. X%alias%
  217. options for alias:
  218. alias                           print all namelists
  219. alias name                      print namelist associated with name
  220. alias name namelist             set "name" to value of namelist.
  221. unalias namelist                unalias names in namelist
  222. X
  223. A "namelist" consists of one or more addresses. An address
  224. may be a name already set to another list, valid user, file
  225. or program.  Filenames must be full pathnames beginning with
  226. a '/' (or a ~ expanding to a home directory).  A "program"
  227. must start with a pipe and be encased in quotes:
  228. X
  229. X    "|program_name"
  230. X
  231. The command, "expand", will print addresses (including sublists)
  232. associated with the given alias.
  233. X%%
  234. X
  235. X%from%
  236. With no arguments, from will print the current message's header.
  237. If given a message list, from will print the headers of those
  238. messages which are in the list.
  239. X
  240. The special arguments, `-' and `+' can be given to move the
  241. current message pointer to the previous or next message
  242. respectively while also printing that message's header.
  243. X
  244. If a message list was given in addition to `-' or `+', then
  245. the current message pointer will be set to the first or last
  246. message, respectively, in the message list given.
  247. X
  248. from - 10-30 {16}
  249. will print the headers of messages 10 through 30 except for
  250. message 16 and set the current message pointer to 10.
  251. X
  252. pick -f Dan | from +
  253. will print the headers of all messages that contain Dan in
  254. in the author's name and set the current message pointer to
  255. the last one of that kind in the list.
  256. X
  257. from +
  258. will print the header of the message after the current message
  259. and increment the current message pointer to the next message.
  260. X%%
  261. X
  262. X%own_hdrs%
  263. Here is where you set, unset or view your own message headers.
  264. These headers are included in all your outgoing mail.
  265. X
  266. options for my_hdrs:
  267. my_hdr                          all headers
  268. my_hdr header                   value associated with header
  269. my_hdr header: string           set header to string
  270. un_hdr header                   unset header
  271. X%%
  272. X
  273. X%fkey_help%
  274. fkey's are function key settings in Suntools (graphics) mode
  275. When run as a tool (-t on command line), choose the Options Item,
  276. and the function key menu option.
  277. X%%
  278. X
  279. X%func_help%
  280. cmd's are just like aliases in the c-shell.
  281. cmd                     view all commands
  282. cmd `command'           value associated with command
  283. cmd `command' "value"   set command to value
  284. uncmd `command'         unset command
  285. X
  286. If you want to reference history commands within a cmd,
  287. escape the ! with a backslant. For example:
  288. X
  289. mail> cmd r 'replysender \!* ; delete -t'
  290. X
  291. will reply using whatever arguments you will have given
  292. on the command line and then delete that message and
  293. then print the next message (-t argument to "delete").
  294. X%%
  295. X
  296. X%headers%
  297. usage: headers [+ | - | N] [-H:c]
  298. print out a screenful of headers.
  299. X+  print the next screenful.
  300. X-  print the previous screenful.
  301. N  (where N is a number) print a screenful starting at N.
  302. set show_deleted to list deleted messages.
  303. cmd h headers        look like UCB-Mail
  304. cmd H Headers        show deleted messages (or set show_deleted)
  305. cmd z headers +      `z' is next screenful
  306. X
  307. Arguments to the headers command include -H:c where `c' is one of
  308. X    n    just print messages headers of NEW messages
  309. X    d    deleted messages
  310. X    u    unread messages
  311. X    o    old messages
  312. X    r    messages that have been replied to
  313. X    a    all messages (mostly for the command line argument -H:c)
  314. X
  315. piping to headers will print the headers of the "output" messages.
  316. X%%
  317. X
  318. X%hdr_format%
  319. set hdr_format="string" for changing the display of message headers.
  320. The string uses printf style formatting and follows these conventions:
  321. X    %f  "from" field (author).
  322. X    %a  the address of the author.
  323. X    %n  the name of the author.
  324. X    %t  "to" field (recipients).
  325. X    %d  date of the message.
  326. X    %T  the time only of the message
  327. X    %N  the day number of the month of the message
  328. X    %D  the day or the week (Sun, Mon, etc.)
  329. X    %M  the month name of the message
  330. X    %Y  the year of the message
  331. X    %s  subject of the message.
  332. X    %l  number of lines in the message.
  333. X    %c  number of characters (bytes) in the message.
  334. X    \n  a newline
  335. X    \t  a tab.
  336. A field specifier may be used.  Thus, %20f will print the first 20
  337. characters of the from line.  No matter what the formatting string,
  338. the message number followed by a '>' (if current message) is printed.
  339. X%%
  340. X
  341. X%folder_help%
  342. usage: folder [-N] [-r] [!] [ %[user] | # | & | file ]
  343. Change current folder.
  344. No arguments prints current folder.
  345. X-N: No headers are displayed upon entering new folder (also command line).
  346. X-r: read only mode (you won't be able to write changes to this folder).
  347. If `!' is specified, current folder is not updated.
  348. X%[user] folder to /usr/spool/mail/[user] (you default)
  349. X#  folder accessed previous to current folder
  350. X&  "mbox" -- default is ~/mbox; or set mbox = "file"
  351. X%%
  352. X
  353. X%prompt%
  354. set prompt = "string"
  355. X"string" is follows printf style formatting conventions:
  356. X    \t, \n will be replaced by a tab or newline respectively.
  357. X    %m     current message number
  358. X    %t     total number of messages
  359. X    %d     number of deleted messages
  360. X    %u     number of unread messages
  361. X    %n     number of new messages
  362. X    %f     name of the current working folder
  363. X    %T     current time
  364. X    %D     day of the week
  365. X    %Y     year
  366. X    %M     month
  367. X    %N     number of the day in the month (date)
  368. X%%
  369. X
  370. X%quit_help%
  371. usage: quit/exit",
  372. quit will update your mailbox; if new mail has come in, you will be
  373. told so and given an option whether to really quit or not.
  374. X"exit" will leave mail not updating your mailbox nor check for new mail.
  375. X%%
  376. X
  377. X%ls%
  378. The ls command is exactly like the UNIX command, "ls."
  379. All arguments are the same.  The variable "lister" can
  380. be set to always default to the same arguments avoiding
  381. having to specify them all the time.  The "folders"
  382. command is nothing more than doing "ls $folder" from
  383. the Mush prompt.
  384. X%%
  385. X
  386. X%shell%
  387. usage: sh [command]
  388. If a "command" is given, that UNIX command will be executed
  389. under the Bourne shell. If no command is specified, then an
  390. interactive shell will be started. The environment variable
  391. SHELL or the local mail shell variable shell  describes the
  392. shell to invoke.  If none is set, then the default shell is
  393. defined by the system administrator (currently set to csh).
  394. X
  395. Users on systems with job control will probably have little
  396. use for the sh command.
  397. X%%
  398. X
  399. X%stop%
  400. The stop command sends a stop signal to the mail shell.
  401. It is equivalent to ^Z as it will stop the process.
  402. Since the shell never needs to be exited, the command
  403. X'q' may be aliased to "stop" and the shell may have,
  404. X% alias 'mail   ?mush'
  405. which will bring mush into the foreground rather than
  406. having to invoke a new shell.  New mail will be read 
  407. into the shell automatically and much time and energy 
  408. is saved.
  409. X%%
  410. X
  411. X%curses%
  412. The curses-based interface for Mush does not require a graphics
  413. display, but does requires a terminal which can handle upline
  414. cursor movement capabilities.  All commands are one key-stroke
  415. commands and are executed instantaneously.  A list of curses
  416. commands is given by using the `?' key in curses mode.
  417. X%%
  418. X
  419. X%bind%
  420. Binding is done for the curses interface only.  It allows
  421. the user to bind keystrokes or key sequences to commands.
  422. X
  423. To bind keystrokes that are control characters, you must use
  424. the notation: "\CX" where "X" is in upper-case and it represents
  425. the control key you want to use. "\CN" would be control-N; "\n"
  426. is carriage return.  You may not bind keyboard generated signals;
  427. for most users, those key sequences are control-C and control-\.
  428. For users with job control, control-Z and control-Y are ignored.
  429. To reference the escape key, use the string, "\E".
  430. X
  431. The spacebar may not be bound since it is the only way to return
  432. to the main level from the "...continue..." prompt.
  433. X
  434. Trying to bind a key sequence which prefixes another sequence
  435. is an error and the user is warned that the longer binding will
  436. not work.
  437. X
  438. As always, -? will give help.
  439. X%%
  440. X
  441. X%msg_flags%
  442. usage: flags [msg_list [N O R D P U R r] ]
  443. This command displays the state of messages as seen by the internals
  444. of Mush.  This is not a documented command, so don't tell anyone.
  445. If a list is given (or piped), it will tell which bits of the message
  446. are set: New, Old, Read, Deleted, Preserved, Unread, Read, and replied.
  447. If any (one or more) of the optional bits are given, then it will set
  448. the appropriate bit in the list given.  As usual, if no list is given,
  449. then the current message is used (or set bits on a pipe).
  450. X%%
  451. X
  452. X%setenv%
  453. usage: setenv VARIABLE [value]
  454. X
  455. Variable names may be any string, but traditionally environment variables
  456. are all upper case.  If no "value" is specified, then the variable name
  457. will be set to an empty string.  If the value contains spaces, you should
  458. enclose the string in quotation marks.  Use printenv to print a list of
  459. all your environment variables.
  460. X%%
  461. X
  462. X%unsetenv%
  463. usage: unsetenv VARIABLE
  464. X
  465. You must specify one and only one variable to unset in your environment
  466. variable settings.  Use printenv to print a list of all your environment
  467. variables.
  468. X%%
  469. END_OF_FILE
  470. if test 16430 -ne `wc -c <'cmd_help'`; then
  471.     echo shar: \"'cmd_help'\" unpacked with wrong size!
  472. fi
  473. # end of 'cmd_help'
  474. fi
  475. if test -f 'fkeys.c' -a "${1}" != "-c" ; then 
  476.   echo shar: Will not clobber existing file \"'fkeys.c'\"
  477. else
  478. echo shar: Extracting \"'fkeys.c'\" \(13831 characters\)
  479. sed "s/^X//" >'fkeys.c' <<'END_OF_FILE'
  480. X/* @(#)fkeys.c        (c) copyright 10/18/86 (Dan Heller) */
  481. X
  482. X#include "mush.h"
  483. X#define draw(x1,y1,x2,y2,OP) pw_vector(msg_win, x1,y1,x2,y2,OP,1)
  484. X#define box(x1,y1,x2,y2,OP)  \
  485. X    draw(x1,y1, x1,y2,OP), draw(x1,y2, x2,y2,OP), \
  486. X        draw(x2,y2, x2,y1,OP), draw(x2,y1, x1,y1,OP)
  487. X
  488. struct cmd fkey_cmds[] = {
  489. X    { "top", fkey_cmd }, { "close", fkey_cmd }, { "bottom", fkey_cmd },
  490. X    { "move", fkey_cmd }, { "stretch", fkey_cmd }, { "repaint", fkey_cmd },
  491. X    { "settings", fkey_settings }, { NULL, quit }
  492. X};
  493. X
  494. X#define L(n)        KEY_LEFTFIRST+(n)-1
  495. X#define R(n)        KEY_RIGHTFIRST+(n)-1
  496. X#define F(n)        KEY_TOPFIRST+(n)-1
  497. X#define BREAK_KEY    KEY_TOPLAST
  498. X
  499. char *leftkey_default_settings[] = {
  500. X    "Left Function Key Settings",
  501. X    "Unused",        /* L1  */    "next",          /* L2  */
  502. X    "undelete",         /* L3  */    "delete",         /* L4  */
  503. X    "replyall",      /* L5  */    "replysender",       /* L6  */
  504. X    "mail",        /* L7  */    "Unset",        /* L8  */
  505. X    "lpr",          /* L9  */    "settings L",      /* L10 */
  506. X    0
  507. X};
  508. X
  509. char *topkey_default_settings[] = {
  510. X    "Top Function Key Settings",
  511. X    "top",        /* T1  */     "close",            /* T2  */
  512. X    "move",        /* T3  */     "stretch",     /* T4  */
  513. X    "bottom",        /* T5  */     "repaint",       /* T6  */
  514. X    "Unset",        /* T7  */     "Unset",        /* T8  */
  515. X    "settings F",     /* T9  */
  516. X    0
  517. X};
  518. X
  519. char *rightkey_default_settings[] = {
  520. X    "Right Function Key Settings",
  521. X    "Unset",        /* R1  */     "Unset",         /* R2  */
  522. X    "Unset",        /* R3  */     "Unset",         /* R4  */
  523. X    "Unset",        /* R5  */     "Unset",         /* R6  */
  524. X    "Unset",        /* R7  */     "Unset",         /* R8  */
  525. X    "Unset",        /* R9  */     "Unset",         /* R10 */
  526. X    "Unset",        /* R11 */     "Unset",         /* R12 */
  527. X    "Unset",        /* R13 */     "Unset",         /* R14 */
  528. X    "settings R",       /* R15 */
  529. X    0
  530. X};
  531. X
  532. X/*
  533. X * Execute commands defined by a function key.
  534. X * Left keys:
  535. X * L1 = (null)  can't be set
  536. X * L2 ... L10
  537. X * Top function keys
  538. X * F1 ... F9, BREAK/backspace (key not definable)
  539. X * Right function keys
  540. X * R1 ... R15
  541. X * Usually, the last Function key displays the others' settings.
  542. X */
  543. fkey(key)
  544. register char *key;
  545. X{
  546. X    register char **argv, *p;
  547. X    char buf[256];
  548. X    int n;
  549. X
  550. X    /* user defined here...        ... default settings here */
  551. X    if (!strncmp((p = key_set_to(key)), "Un", 2)) {
  552. X    print("Funciton key: %s  %s", key, p);
  553. X    return 0;
  554. X    }
  555. X    /* make_command will screw up "p", so copy it first */
  556. X    (void) strcpy(buf, p);
  557. X    Debug("(%s) \"%s\": ", key, p), turnon(glob_flags, CONT_PRNT);
  558. X    if (argv = make_command(buf, TRPL_NULL, &n))
  559. X    (void) do_command(n, argv, msg_list);
  560. X    return -1;
  561. X}
  562. X
  563. fkey_settings(i, argv)
  564. register char i;
  565. register char **argv;
  566. X{
  567. X    register char key, *p, **fkey_str;
  568. X    char buf[256];
  569. X    char *help_args[17];
  570. X
  571. X    if (!*++argv) {
  572. X    print("Must specify one of L, F or R to identify a function key set");
  573. X    return -1;
  574. X    }
  575. X    key = **argv;
  576. X    switch(Upper(key)) {
  577. X    when 'L': fkey_str = leftkey_default_settings;
  578. X    when 'F': fkey_str = topkey_default_settings;
  579. X    when 'R': fkey_str = rightkey_default_settings;
  580. X    otherwise: print("Invalid key set: %c (choose L, F or R)", key);
  581. X           return -1;
  582. X    }
  583. X    help_args[0] = fkey_str[0];
  584. X    for (i = 1; fkey_str[i]; i++) {
  585. X    p = key_set_to(sprintf(buf, "%c%d", key, i));
  586. X    help_args[i] = savestr(sprintf(buf, "%c%-2.d       %s", key, i, p));
  587. X    }
  588. X    help_args[i] = 0;  /* null terminate list */
  589. X    (void) help(print_sw->ts_windowfd, help_args, NULL);
  590. X
  591. X    free_vec(help_args+1);
  592. X    return 0;
  593. X}
  594. X
  595. char *
  596. key_set_to(p)
  597. register char *p;
  598. X{
  599. X    register char *p2, **fkey_str;
  600. X
  601. X    switch(*p) {
  602. X    when 'L': fkey_str = leftkey_default_settings;
  603. X    when 'F': fkey_str = topkey_default_settings;
  604. X    when 'R': fkey_str = rightkey_default_settings;
  605. X    }
  606. X    p2 = do_set(fkeys, p);
  607. X    return (p2)? p2: fkey_str[atoi(p+1)];
  608. X}
  609. X
  610. fkey_cmd(x, p)
  611. register char **p;
  612. X{
  613. X    if (!strcmp(*p, "close"))
  614. X    toolquit(NO_ITEM, 0, NO_EVENT);
  615. X    else if (!strcmp(*p, "top"))
  616. X    wmgr_top(tool->tl_windowfd, rootfd);
  617. X    else if (!strcmp(*p, "move"))
  618. X    wmgr_move(tool->tl_windowfd, rootfd);
  619. X    else if (!strcmp(*p, "stretch"))
  620. X    wmgr_stretch(tool->tl_windowfd, rootfd);
  621. X    else if (!strcmp(*p, "bottom"))
  622. X    wmgr_bottom(tool->tl_windowfd, rootfd);
  623. X    else if (!strcmp(*p, "repaint"))
  624. X    wmgr_refreshwindow(tool->tl_windowfd, rootfd);
  625. X    return -1;
  626. X}
  627. X
  628. X/* execute a command given a function key, if the key is user defined,
  629. X * call fkey() at top of file. Parameter is the key number in "ascii"
  630. X */
  631. func_key(key)
  632. register int key;
  633. X{
  634. X    register char *p;
  635. X    char buf[4];
  636. X    int nkey;
  637. X
  638. X    if (key >= KEY_LEFTFIRST && key <= KEY_LEFTLAST)
  639. X    buf[0] = 'L', nkey = key - KEY_LEFTFIRST;
  640. X    else if (key >= KEY_TOPFIRST && key <= KEY_TOPLAST)
  641. X    buf[0] = 'F', nkey = key - KEY_TOPFIRST;
  642. X    else if (key >= KEY_RIGHTFIRST && key <= KEY_RIGHTLAST)
  643. X    buf[0] = 'R', nkey = key - KEY_RIGHTFIRST;
  644. X    (void) sprintf(buf+1, "%d", nkey+1);
  645. X
  646. X    return fkey(buf);
  647. X}
  648. X
  649. void
  650. set_fkeys()
  651. X{
  652. X    ready(display_keys() + 10);
  653. X    print_valid_functions(txt.y+20);
  654. X    getting_opts = 2;
  655. X    win_setcursor(msg_sw->ts_windowfd, &checkmark);
  656. X}
  657. X
  658. char *MSG = "Click the appropriate mouse button over a function key";
  659. ready(Y)
  660. X{
  661. X    static int y;
  662. X    int x = (msg_rect.r_width - strlen(MSG)*l_width(LARGE))/2;
  663. X    if (Y)
  664. X    y = Y;
  665. X    Clrtoeol(msg_win, (txt.x = 0), (txt.y = y), LARGE);
  666. X    highlight(msg_win, x, y, LARGE, MSG);
  667. X}
  668. X
  669. X/* number of pixels in x and y directions describing the size of a graphical
  670. X * function key.  they represent the little keys and big keys respectively.
  671. X */
  672. X/* static struct pr_pos fkey_sizes[2] = { { 23, 23 }, { 50, 23 } }; */
  673. static struct pr_pos fkey_sizes[2] = { { 24, 23 }, { 52, 23 } };
  674. X
  675. X#define BORDER        4   /* border (distance) between keys */
  676. X#define KEYTOP        15  /* distance from top to start drawing */
  677. X#define LEFT_START    15  /* pixels from left to start drawing boxes */
  678. X#define TOP_START    (LEFT_START+2*fkey_sizes[0].x + fkey_sizes[1].x+BORDER)
  679. X#define RIGHT_START    (TOP_START + 5*(fkey_sizes[0].x+BORDER) + \
  680. X                     5*(fkey_sizes[1].x+BORDER))
  681. X
  682. X/*
  683. X * if !p, we're setting key at location x,y.
  684. X * else Set that key to this string (p).
  685. X */
  686. void
  687. set_key(p, x,y)
  688. register char *p;
  689. register int x,y;
  690. X{
  691. X    char     buf[256], **argv;
  692. X    static char *key;
  693. X    int     argc;
  694. X
  695. X    static int key_x, key_y;
  696. X    if (!p) {
  697. X    if (key = find_key(x,y)) {
  698. X        print("Type new setting for key: %s", key);
  699. X        (void) sprintf(buf, "Function key \"%s\": ", key);
  700. X        highlight(msg_win, 20, txt.y, LARGE, buf);
  701. X        txt.x = 20 + strlen(buf)*l_width(LARGE);
  702. X        Clrtoeol(msg_win, txt.x, txt.y, LARGE);
  703. X        type_cursor(PIX_SRC);
  704. X    } else
  705. X        ready(0);
  706. X    key_x = x, key_y = y;
  707. X    } else {
  708. X    u_long save_bang = ison(glob_flags, IGN_BANG);
  709. X    if (!*p)
  710. X        (void) sprintf(buf, "unfkey %s", key);
  711. X    else
  712. X        (void) sprintf(buf, "fkey %s \"%s\"", key, p);
  713. X    turnon(glob_flags, IGN_BANG);
  714. X    if (argv = make_command(buf, TRPL_NULL, &argc)) {
  715. X        (void) do_command(argc, argv, msg_list);
  716. X        print("Function key %s:  %s", key, key_set_to(key));
  717. X    }
  718. X    if (!save_bang)
  719. X        turnoff(glob_flags, IGN_BANG);
  720. X    ready(0);
  721. X    }
  722. X}
  723. X
  724. X/* passed the x and y coords of a mouse click, return the function key
  725. X * that exists in that position. NULL if no key there.  string will be
  726. X * something like "L6" or "F9" or "R12"
  727. X */
  728. char *
  729. find_key(x,y)
  730. int x, y;
  731. X{
  732. X    static char buf[6];
  733. X    int row, col;
  734. X    static int old_left, old_top, old_right, old_bot;
  735. X
  736. X    if (!(row = find_y(&y)))
  737. X    return NULL;
  738. X    if (x < LEFT_START || x > RIGHT_START + 3*(fkey_sizes[0].x+BORDER))
  739. X    return NULL;   /* out of range */
  740. X    if (x > LEFT_START && x < TOP_START-fkey_sizes[0].x - BORDER) {
  741. X    if ((col = (x > LEFT_START + fkey_sizes[0].x + BORDER)+1) == 1)
  742. X        x = LEFT_START+1;
  743. X    else x = LEFT_START + fkey_sizes[0].x + BORDER + 1;
  744. X    if (col == 1 && row == 1)
  745. X        return NULL;
  746. X    /* unhighlight the old function key image */
  747. X    if (old_left)
  748. X        box(old_left, old_top, old_right, old_bot, PIX_CLR);
  749. X    old_left = x, old_top = y;
  750. X    old_right = x+fkey_sizes[(col != 1)].x-2, old_bot = y+fkey_sizes[0].y-2;
  751. X    /* highlight most recently selected function key image */
  752. X    box(x,y, old_right, old_bot, PIX_SRC);
  753. X
  754. X    return sprintf(buf, "L%d", col + 2*(row-1));
  755. X    }
  756. X    if (x > TOP_START && x < RIGHT_START - fkey_sizes[0].x - BORDER) {
  757. X    int which;
  758. X    if (row > 1)
  759. X        return NULL;
  760. X    which = (x - TOP_START) / (fkey_sizes[0].x + BORDER) + 1;
  761. X    if (which == 15)
  762. X        return NULL;   /* Can't set break key (backspace on a sun3) */
  763. X    if (which == 14)
  764. X        x = TOP_START + ((which = 9)-2) * (fkey_sizes[1].x+BORDER) -
  765. X            fkey_sizes[0].x - BORDER + 1;
  766. X    else if (which <= 2)
  767. X        x = TOP_START + (which-1) * (fkey_sizes[0].x+BORDER) + 1;
  768. X    else {
  769. X        which = (which+3)/2;
  770. X        x = TOP_START + (which-2) * (fkey_sizes[1].x+BORDER) + 1;
  771. X    }
  772. X
  773. X    /* unhighlight the old function key image */
  774. X    if (old_left)
  775. X        box(old_left, old_top, old_right, old_bot, PIX_CLR);
  776. X    old_left = x, old_top = y;
  777. X    old_right = x+fkey_sizes[(which > 2 && which < 8)].x-2;
  778. X    old_bot = y+fkey_sizes[0].y-2;
  779. X    /* highlight most recently selected function key image */
  780. X    box(x,y, old_right, old_bot, PIX_SRC);
  781. X
  782. X    return sprintf(buf, "F%d", which);
  783. X    }
  784. X    if (x > RIGHT_START) {
  785. X    if (x < RIGHT_START + fkey_sizes[0].x)
  786. X        x = RIGHT_START+1, col = 1;
  787. X    else if (x < RIGHT_START + fkey_sizes[0].x + BORDER)
  788. X        return NULL;  /* cursor was clicked between keys */
  789. X    else if (x < RIGHT_START + 2*fkey_sizes[0].x + BORDER)
  790. X        x = RIGHT_START+fkey_sizes[0].x+BORDER+1, col = 2;
  791. X    else if (x < RIGHT_START + 2 * (fkey_sizes[0].x+BORDER))
  792. X        return NULL;  /* click between keys again */
  793. X    else x = RIGHT_START + 2*(fkey_sizes[0].x+BORDER)+1, col = 3;
  794. X
  795. X    /* unhighlight the old function key image */
  796. X    if (old_left)
  797. X        box(old_left, old_top, old_right, old_bot, PIX_CLR);
  798. X    old_left = x, old_top = y;
  799. X    old_right = x+fkey_sizes[0].x-2, old_bot = y+fkey_sizes[0].y-2;
  800. X    /* highlight most recently selected function key image */
  801. X    box(x,y, old_right, old_bot, PIX_SRC);
  802. X
  803. X    return sprintf(buf, "R%d", col + 3*(row-1));
  804. X    }
  805. X    return NULL;
  806. X}
  807. X
  808. X/* find_y will find which row in a function key pad a y coordinate
  809. X * represents. return 1,2,3,4, or 5   0 if inbetween rows
  810. X */
  811. find_y(y)
  812. register int *y;
  813. X{
  814. X    int Y, y_incr = fkey_sizes[0].y, ret_value = 0;
  815. X    for (Y = KEYTOP; Y <= KEYTOP + 6*y_incr + 4 * BORDER; Y += y_incr + BORDER)
  816. X    if (*y < Y) {
  817. X        *y = (Y - y_incr - BORDER) + 1;
  818. X        return ret_value;
  819. X    } else ret_value++;
  820. X    return 0;
  821. X}
  822. X
  823. char *l_msg = "Specifies which function key for setting value";
  824. char *m_msg = "Display current value for function key";
  825. char *r_msg = "Help setting and viewing function key values";
  826. X
  827. display_keys()
  828. X{
  829. X    register int i, x,y;
  830. X    register char *p;
  831. X
  832. X    do_clear();
  833. X
  834. X    x = LEFT_START, y = KEYTOP;
  835. X    /* print left keys */
  836. X    for (i = 0; i < 10; i++) {
  837. X    box(x, y, x + fkey_sizes[i%2].x, y + fkey_sizes[i%2].y, PIX_SRC);
  838. X    box(x+2, y+2, x+fkey_sizes[i%2].x-2, y+fkey_sizes[i%2].y-2, PIX_SRC);
  839. X    if (i && (p = find_key(x+4,y+4)))
  840. X        pw_text(msg_win, x+3, y+3+l_height(SMALL), PIX_SRC,fonts[SMALL], p);
  841. X    else pw_replrop(msg_win, x+3, y+3, fkey_sizes[0].x-5, fkey_sizes[0].y-5,
  842. X         PIX_SRC | PIX_DST, &shade_50, 0,0);
  843. X    if (i % 2)
  844. X        y += fkey_sizes[0].y + BORDER, x = LEFT_START;
  845. X    else
  846. X        x += fkey_sizes[0].x + BORDER;
  847. X    }
  848. X
  849. X    x = TOP_START, y = KEYTOP;
  850. X    /* print top keys */
  851. X    for (i = 1; i <= 10; i++) {
  852. X    register int n = (i >= 3 && i <= 7);
  853. X    box(x, y, x + fkey_sizes[n].x, y + fkey_sizes[n].y, PIX_SRC);
  854. X    box(x+2, y+2, x + fkey_sizes[n].x-2, y + fkey_sizes[n].y-2, PIX_SRC);
  855. X    if (i != 10 && (p = find_key(x+4,y+4)))
  856. X        pw_text(msg_win, x+3, y+3+l_height(SMALL), PIX_SRC,fonts[SMALL], p);
  857. X    /* shade the break key (backspace on sun3's) -- can't set */
  858. X    else if (i == 10)
  859. X        pw_replrop(msg_win, x+3, y+3, fkey_sizes[n].x-5, fkey_sizes[n].y-5,
  860. X         PIX_SRC | PIX_DST, &shade_50, 0,0);
  861. X    x += fkey_sizes[n].x + BORDER;
  862. X    }
  863. X
  864. X    x = RIGHT_START;
  865. X    /* print right keys */
  866. X    for (i = 0; i < 15; i++) {
  867. X    box(x, y, x + fkey_sizes[0].x, y + fkey_sizes[0].y, PIX_SRC);
  868. X    box(x+2, y+2, x + fkey_sizes[0].x-2, y + fkey_sizes[0].y-2, PIX_SRC);
  869. X    if (p = find_key(x+4,y+4))
  870. X        pw_text(msg_win, x+3, y+3+l_height(SMALL),PIX_SRC, fonts[SMALL], p);
  871. X    if (!((i+1) % 3))
  872. X        y += fkey_sizes[0].y + BORDER, x -= 2*(fkey_sizes[0].x + BORDER);
  873. X    else
  874. X        x += fkey_sizes[0].x + BORDER;
  875. X    }
  876. X    x = TOP_START;
  877. X    y = KEYTOP + BORDER + fkey_sizes[0].y + l_height(DEFAULT);
  878. X    pw_rop(msg_win, x, y-11, 16,16, PIX_SRC, &mouse_left, 0,0);
  879. X    pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], l_msg);
  880. X
  881. X    y += BORDER + fkey_sizes[0].y;
  882. X    pw_rop(msg_win, x,y-11, 16,16, PIX_SRC, &mouse_middle, 0,0);
  883. X    pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], m_msg);
  884. X
  885. X    y += BORDER + fkey_sizes[0].y;
  886. X    pw_rop(msg_win, x,y-11, 16,16, PIX_SRC, &mouse_right, 0,0);
  887. X    pw_text(msg_win, x+30, y, PIX_SRC, fonts[DEFAULT], r_msg);
  888. X
  889. X    x = (msg_rect.r_width - 26*l_width(DEFAULT))/2;
  890. X    y += BORDER + fkey_sizes[0].y;
  891. X    highlight(msg_win, x, y, DEFAULT, "You may not set shaded keys");
  892. X
  893. X    y += BORDER + fkey_sizes[0].y + 15;
  894. X    for (i = 0; i < BORDER; i++)
  895. X    draw(0, y+i, msg_rect.r_width, y+i, PIX_SRC);
  896. X    y += 10;
  897. X    for (i = 0; i < BORDER; i++)
  898. X    draw(0, y+l_height(LARGE)+i, msg_rect.r_width, y+l_height(LARGE)+i,
  899. X         PIX_SRC);
  900. X    return y;
  901. X}
  902. X
  903. print_valid_functions(y)
  904. register int y;
  905. X{
  906. X    register int x, n, cmd_len = 12 * l_width(DEFAULT);
  907. X    register char *p;
  908. X
  909. X    y += 20, x = (msg_rect.r_width - 25*l_width(LARGE))/2;
  910. X    highlight (msg_win, x, y, LARGE, "Available Command Names");
  911. X    y += 20, x = 30;
  912. X    for (n = 0; p = cmds[n].command; n++) {
  913. X    if (x + cmd_len > msg_rect.r_width - 5)
  914. X        y += l_height(DEFAULT), x = 30;
  915. X    pw_text(msg_win, x, y, PIX_SRC, fonts[DEFAULT], p);
  916. X    x += cmd_len;
  917. X    }
  918. X    for (n = 0; p = fkey_cmds[n].command; n++) {
  919. X    if (x + cmd_len > msg_rect.r_width - 5)
  920. X        y += l_height(DEFAULT), x = 30;
  921. X    pw_text(msg_win, x, y, PIX_SRC, fonts[DEFAULT], p);
  922. X    x += cmd_len;
  923. X    }
  924. X}
  925. END_OF_FILE
  926. if test 13831 -ne `wc -c <'fkeys.c'`; then
  927.     echo shar: \"'fkeys.c'\" unpacked with wrong size!
  928. fi
  929. # end of 'fkeys.c'
  930. fi
  931. if test -f 'select.c' -a "${1}" != "-c" ; then 
  932.   echo shar: Will not clobber existing file \"'select.c'\"
  933. else
  934. echo shar: Extracting \"'select.c'\" \(13055 characters\)
  935. sed "s/^X//" >'select.c' <<'END_OF_FILE'
  936. X/* select.c    (c) copyright 1986 (Dan Heller) */
  937. X
  938. X/* 
  939. X * Routine which handle io (selection on file descriptors) between user and
  940. X * the various windows.
  941. X *
  942. X * In toolmode, the user types characters and each character is interpreted
  943. X * here and, if applicable, is sent to rite.c where it is appended to a 
  944. X * string similar to a tty driver and fgets. When the user types a '\n' the
  945. X * rite() routine returns the string and we call add_to_letter to append the
  946. X * string to the letter.  Signals are caught here as well.  that is the signal
  947. X * characters setup by the user are checked and if one matches, call the signal
  948. X * handling routine as if there were a real signal.
  949. X *
  950. X * Mouse handling is done here. See code for more detail.
  951. X */
  952. X#include "mush.h"
  953. X
  954. X#define READ_MSG    (char *)'r'
  955. X#define DEL_MSG        (char *)'d'
  956. X#define UNDEL_MSG    (char *)'u'
  957. X#define REPL_MSG    (char *)'R'
  958. X#define SAVE_MSG    (char *)'s'
  959. X#define PRNT_MSG    (char *)'p'
  960. X#define PRE_MSG        (char *)'P'
  961. X#define E_EDIT         (char *)'e'
  962. X#define E_VIEW         (char *)'v'
  963. X#define E_INCLUDE      (char *)'i'
  964. X#define E_SEND        (char *)'S'
  965. X#define E_ABORT       (char *)'a'
  966. X#define MENU_HELP    (char *)'h'
  967. X#define O_SAVE        (char *)'s'
  968. X#define O_QUIT        (char *)'q'
  969. X#define O_RSTR        (char *)'r'
  970. X
  971. X#define N_MENU_ITEMS    8
  972. X#define E_MENU_ITEMS    6
  973. X
  974. msg_io(gfxsw, ibits, obits, ebits, timer)
  975. register struct gfxsubwindow *gfxsw;
  976. register int *ibits,*obits,*ebits;
  977. struct timeval **timer;
  978. X{
  979. X    register char    *p;
  980. X    struct inputevent     event;
  981. X    static char     lastchar;
  982. X    static int         line, count;
  983. X
  984. X    if (*ibits & ~(1 << gfxsw->gfx_windowfd)) {
  985. X    *ibits = *obits = *ebits = 0;
  986. X    return;
  987. X    }
  988. X    if (input_readevent(msg_sw->ts_windowfd, &event) == -1) {
  989. X    error("input event");
  990. X    return;
  991. X    }
  992. X    /*
  993. X    if (ID == LOC_WINENTER) {
  994. X    int x;
  995. X    struct inputmask im;
  996. X    win_getinputmask(gfxsw->gfx_windowfd, &im, &x);
  997. X    win_setinputmask(hdr_sw->ts_windowfd, &im, &im, x);
  998. X    }
  999. X    */
  1000. X    if (ID >= KEY_LEFTFIRST)
  1001. X    if (ison(glob_flags, IS_GETTING))
  1002. X        print("Finish editing letter first");
  1003. X    else
  1004. X        (void) func_key(ID);
  1005. X    else if (isascii(ID) && (msg_pix || ison(glob_flags, IS_GETTING) ||
  1006. X    getting_opts)) {
  1007. X    if (getting_opts) {
  1008. X        /*
  1009. X         * txt.x <= 5 indicates not to accept typed input for options
  1010. X         * and function key setting.
  1011. X         */
  1012. X        if (txt.x > 5) {
  1013. X        /* ^C, ^\ or ^U kills line */
  1014. X        type_cursor(PIX_XOR);
  1015. X        if (ID == tchars.t_intrc || ID == tchars.t_quitc ||
  1016. X                        ID == _tty.sg_kill) {
  1017. X            rite(_tty.sg_kill), txt.x = 5;
  1018. X            if (getting_opts == 1)
  1019. X            option_line(line), display_opts(0);
  1020. X            else
  1021. X            set_key(0, 0, 0);
  1022. X        } else if (p = rite((char)ID)) {
  1023. X            /* if no string entered, preserve old value */
  1024. X            if (*p && getting_opts == 1)
  1025. X            add_opt(p, line);
  1026. X            if (getting_opts == 2)
  1027. X            set_key(p, 0,0);
  1028. X        } else
  1029. X            type_cursor(PIX_XOR);
  1030. X        }
  1031. X    }
  1032. X    /*
  1033. X     * This section MUST BE BEFORE the following "is_getting" section.
  1034. X     * If user displays a message while editing a letter, he must hit 'q'
  1035. X     * to return to edit mode.  He may not edit a new letter while one is
  1036. X     * already being edited.
  1037. X     */
  1038. X    else if (msg_pix)
  1039. X        if (isdigit(ID)) {
  1040. X        if (!isdigit(lastchar))
  1041. X            count = 0;
  1042. X        count = count * 10 + ID - '0';
  1043. X        } else {
  1044. X        /* scroll <count> lines */
  1045. X        if (!count || count > msg_pix->pr_size.y / l_height(curfont))
  1046. X            count = 1;
  1047. X        if (ID == 'k' || ID == 'K' || ID == '-')
  1048. X            scroll_win(-count);
  1049. X        else if (ID == '\n' || ID == '\r' || ID == 'j')
  1050. X            scroll_win(count);
  1051. X        else if (ID == ' ')
  1052. X            scroll_win(crt);
  1053. X        else if ((ID == 'q' || ID == 'Q') &&
  1054. X            ison(glob_flags, IS_GETTING)) {
  1055. X            pr_destroy(msg_pix), msg_pix = (struct pixrect *)NULL;
  1056. X            win_setcursor(msg_sw->ts_windowfd, &write_cursor);
  1057. X            txt.x = 5, txt.y = msg_rect.r_height - l_height(curfont);
  1058. X            wprint("\n(continue editing letter)\n");
  1059. X            clr_bot_line();
  1060. X            type_cursor(PIX_SRC);
  1061. X        }
  1062. X        }
  1063. X    /*
  1064. X     * If msg_pix is NULL, then we are not reading a message. If we are
  1065. X     * editing a letter, then enter the keys typed.  If we are doing
  1066. X     * nothing, ignore this input.
  1067. X     */
  1068. X    else if (ison(glob_flags, IS_GETTING)) {
  1069. X        type_cursor(PIX_XOR);
  1070. X        if (lastchar != ltchars.t_lnextc &&
  1071. X        (ID == tchars.t_intrc || ID == tchars.t_quitc)) {
  1072. X            (void) rite(_tty.sg_kill);
  1073. X            (void) rm_edfile(SIGINT);
  1074. X        } else {
  1075. X        register int n = 1;
  1076. X        if (ID == tchars.t_eofc && txt.x == 5
  1077. X            || (p = rite((char)ID)) && !(n = add_to_letter(p)))
  1078. X            finish_up_letter();
  1079. X        else if (n > 0)
  1080. X            type_cursor(PIX_XOR);
  1081. X        }
  1082. X    }
  1083. X    lastchar = ID;
  1084. X    } else switch(ID) {
  1085. X    when MS_LEFT : case MS_MIDDLE:
  1086. X        if (getting_opts == 2)
  1087. X        if (ID == MS_LEFT)
  1088. X            set_key(NULL, event.ie_locx, event.ie_locy);
  1089. X        else {
  1090. X            register char *p = find_key(event.ie_locx, event.ie_locy);
  1091. X            if (p)
  1092. X            print("Function key %s:  %s", p, key_set_to(p));
  1093. X        }
  1094. X        else if (getting_opts) {
  1095. X        int y = event.ie_locy - 50;
  1096. X        if (y < -24)
  1097. X            break;
  1098. X        if (y < 0) {
  1099. X            register int x = event.ie_locx;
  1100. X            register int X = 60*l_width(LARGE);
  1101. X            if (x >= X && x <= X+16)
  1102. X            display_opts(-1); /* scroll options back one value */
  1103. X            else if (x >= X+20 && x <= X+36)
  1104. X            display_opts(1); /* scroll options forward one value */
  1105. X            break;
  1106. X        }
  1107. X        /* the user was typing something -- stopped by using mouse */
  1108. X        if (txt.x > 5) {
  1109. X            type_cursor(PIX_CLR);
  1110. X            (void) rite(_tty.sg_kill), txt.x = 5;
  1111. X            option_line(line), display_opts(0);
  1112. X        }
  1113. X            line = y/20;
  1114. X        if (ID == MS_LEFT)
  1115. X            toggle_opt(line);
  1116. X        help_opt(line);   /* display help (short info) in both cases */
  1117. X        } else if (msg_pix)
  1118. X        if (ID == MS_LEFT)
  1119. X            scroll_win(crt-3);
  1120. X        else
  1121. X            scroll_win(-(crt-3));
  1122. X    when MS_RIGHT:
  1123. X        if (getting_opts)
  1124. X        (void) view_opts_menu(&event, gfxsw->gfx_windowfd);
  1125. X        else if (isoff(glob_flags, IS_GETTING))
  1126. X        (void) do_menu(&event, gfxsw->gfx_windowfd, current_msg);
  1127. X        else
  1128. X        (void) edit_menu(&event, gfxsw->gfx_windowfd);
  1129. X    otherwise: ;
  1130. X    }
  1131. X    *ibits = *obits = *ebits = 0;
  1132. X}
  1133. X
  1134. struct cursor *mice[3] = { &l_cursor, &m_cursor, &r_cursor };
  1135. X
  1136. hdr_io(gfxsw, ibits, obits, ebits, sw_timer)
  1137. register struct gfxsubwindow *gfxsw;
  1138. int *ibits,*obits,*ebits;
  1139. struct timeval **sw_timer;
  1140. X{
  1141. X    static int         which_cursor;
  1142. X    struct inputmask     im;
  1143. X    struct inputevent     event;
  1144. X    int         line;
  1145. X
  1146. X    if (*ibits & ~(1 << gfxsw->gfx_windowfd)) {
  1147. X    *ibits = *obits = *ebits = 0;
  1148. X    return;
  1149. X    }
  1150. X    /* make curosr change which button is lit */
  1151. X    win_setcursor(gfxsw->gfx_windowfd, mice[which_cursor]);
  1152. X
  1153. X    which_cursor = (which_cursor+1) % 3;
  1154. X    if (input_readevent(hdr_sw->ts_windowfd, &event) == -1) {
  1155. X    error("input event");
  1156. X    return;
  1157. X    }
  1158. X    /* I'm not sure why I have to do this.
  1159. X     * I'm doing it because sometimes the IO hangs completely and no input
  1160. X     * is accepted. What I do here is get the current mask, save it, then
  1161. X     * reset it. This action seems to flush the IO queue, and I don't have hung
  1162. X     * IO anymore.  This shouldn't be necessary, but it appears to work.
  1163. X     * (occurances have droped about 90%)
  1164. X     */
  1165. X    if (ID == LOC_WINENTER) {
  1166. X    int x;
  1167. X    win_getinputmask(gfxsw->gfx_windowfd, &im, &x);
  1168. X    win_setinputmask(hdr_sw->ts_windowfd, &im, &im, x);
  1169. X    }
  1170. X    /* just return -- we just wanted to make the cursor flicker */
  1171. X    if (ID == LOC_STILL || ID == LOC_MOVE || ID == LOC_WINENTER) {
  1172. X    *ibits = *obits = *ebits = 0;
  1173. X    return;
  1174. X    }
  1175. X    line = event.ie_locy / l_height(DEFAULT);
  1176. X    if (ID >= KEY_LEFTFIRST)
  1177. X    (void) func_key(ID);
  1178. X    else if (n_array[line] > msg_cnt)
  1179. X    if (!msg_cnt)
  1180. X        print("-- You have no messages -- ");
  1181. X    else
  1182. X        print("Message out of range.  Place mouse over a legal message.");
  1183. X    else switch(ID) {
  1184. X    when MS_LEFT: case MS_MIDDLE:
  1185. X        (void) do_menu((ID == MS_LEFT)? READ_MSG: DEL_MSG, 0,n_array[line]);
  1186. X    when MS_RIGHT:
  1187. X        (void) do_menu(&event, gfxsw->gfx_windowfd, n_array[line]);
  1188. X    otherwise : print("Unkown ID = %d", ID);
  1189. X    }
  1190. X    *ibits = *obits = *ebits = 0;
  1191. X}
  1192. X
  1193. X/* if "fd" is 0, then event points to the action to be taken.
  1194. X * otherwise, determine action to be taken by displaying a menu.
  1195. X * message is the number current_msg should be changed to (may be the same).
  1196. X */
  1197. do_menu(event, fd, message)
  1198. caddr_t event;
  1199. X{
  1200. X    static char buf[20];
  1201. X    struct menuitem *m_item;
  1202. X    char *action;
  1203. X    static struct menuitem msg_menu_items[] = {
  1204. X    { MENU_IMAGESTRING,  "Read",     READ_MSG   },
  1205. X    { MENU_IMAGESTRING,  "Delete",   DEL_MSG    },
  1206. X    { MENU_IMAGESTRING,  "Undelete", UNDEL_MSG  },
  1207. X    { MENU_IMAGESTRING,  "Reply",    REPL_MSG   },
  1208. X    { MENU_IMAGESTRING,  "Save",     SAVE_MSG   },
  1209. X    { MENU_IMAGESTRING,  "Preserve", PRE_MSG    },
  1210. X    { MENU_IMAGESTRING,  "Print",    PRNT_MSG   },
  1211. X    { MENU_IMAGESTRING,  "Help",     MENU_HELP  }
  1212. X    };
  1213. X    static struct menu help_menu = {
  1214. X        MENU_IMAGESTRING, "Item Help",
  1215. X    N_MENU_ITEMS, msg_menu_items,
  1216. X    (struct menu *)NULL, NULL
  1217. X    };
  1218. X    static struct menu msgs_menu = {
  1219. X        MENU_IMAGESTRING, buf, N_MENU_ITEMS,
  1220. X    msg_menu_items, &help_menu, NULL
  1221. X    };
  1222. X    /* to have the menu stack maintain order of menus upon each invokation,
  1223. X     * declare menu_ptr to be static and remove the following two lines
  1224. X     * after the declaration.
  1225. X     */
  1226. X    struct menu *menu_ptr = &msgs_menu;
  1227. X    msgs_menu.m_next = &help_menu;
  1228. X    help_menu.m_next = (struct menu *)NULL;
  1229. X
  1230. X    if (!msg_cnt) {
  1231. X    print("No Messages.");
  1232. X    return;
  1233. X    }
  1234. X    if (fd) {
  1235. X    (void) sprintf(buf, "Message #%d", message+1);
  1236. X    if (m_item = menu_display(&menu_ptr, (struct inputevent *)event, fd))
  1237. X        action = m_item->mi_data;
  1238. X    else
  1239. X        return;
  1240. X    } else
  1241. X    action = event;
  1242. X
  1243. X    if (menu_ptr == &help_menu || action == MENU_HELP) {
  1244. X    switch(action) {
  1245. X        when DEL_MSG: case UNDEL_MSG:
  1246. X        (void) help(fd, "menu_delete", tool_help);
  1247. X        when READ_MSG: (void) help(fd, "next", tool_help);
  1248. X        when REPL_MSG: (void) help(fd, "menu_respond", tool_help);
  1249. X        when SAVE_MSG: (void) help(fd, "save", tool_help);
  1250. X        when PRE_MSG: (void)  help(fd, "preserve", tool_help);
  1251. X        when PRNT_MSG: (void) help(fd, "printer", tool_help);
  1252. X        when MENU_HELP:
  1253. X        if (menu_ptr == &help_menu)
  1254. X            (void) help(fd, "help_menu_help_msg", tool_help);
  1255. X        else
  1256. X            (void) help(fd, "msg_menu", tool_help);
  1257. X    }
  1258. X    return;
  1259. X    }
  1260. X    set_isread(message);
  1261. X    if (action == SAVE_MSG) {
  1262. X    panel_set(msg_num_item, PANEL_VALUE, sprintf(buf, "%d", message+1), 0);
  1263. X    ((struct inputevent *)event)->ie_code = MS_LEFT;
  1264. X    do_file_dir(save_item, 0, event);
  1265. X    panel_set(msg_num_item, PANEL_VALUE, NO_STRING, 0);
  1266. X    return;
  1267. X    } else if (action == PRNT_MSG  || action == PRE_MSG ||
  1268. X           action == UNDEL_MSG || action == DEL_MSG) {
  1269. X    fkey_misc(action, message);
  1270. X    return;
  1271. X    }
  1272. X    if (isoff(glob_flags, IS_GETTING)) {
  1273. X    current_msg = message;
  1274. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  1275. X    }
  1276. X    if (action == REPL_MSG) {
  1277. X    respond_mail(respond_item, 0, event);
  1278. X    return;
  1279. X    } else if (ison(glob_flags, IS_GETTING)) {
  1280. X    if (exec_pid)
  1281. X        /* User can read a message as long as he's not in an editor */
  1282. X        print("Finish editing message first");
  1283. X    else {
  1284. X        (void) do_hdrs(0, DUBL_NULL, NULL);
  1285. X        display_msg(message, (long)0);
  1286. X    }
  1287. X    return;
  1288. X    }
  1289. X    display_msg(current_msg, (long)0);
  1290. X}
  1291. X
  1292. X/* miscellaneous function key actions there are here because the defines
  1293. X * for DEL_MSG, etc are here in this file and the function is called from
  1294. X * here more often.
  1295. X */
  1296. fkey_misc(action, message)
  1297. char *action;
  1298. X{
  1299. X    int argc;
  1300. X    register char **argv;
  1301. X    char buf[30];
  1302. X
  1303. X    print("Message #%d ", message+1);
  1304. X    if (action == UNDEL_MSG || action == DEL_MSG)
  1305. X    print_more("%sd. ", sprintf(buf, "%selete",
  1306. X                (action == DEL_MSG)? "d": "und"));
  1307. X    else if (action == PRNT_MSG) {
  1308. X    print_more("sent to printer");
  1309. X    (void) strcpy(buf, "lpr");
  1310. X    } else if (action == PRE_MSG)
  1311. X    print_more("%sd", strcpy(buf, "preseve"));
  1312. X    (void) sprintf(&buf[strlen(buf)], " %d", message+1);
  1313. X    if (message == current_msg && action == DEL_MSG)
  1314. X    do_clear();
  1315. X
  1316. X    if (argv = make_command(buf, DUBL_NULL, &argc))
  1317. X    (void) do_command(argc, argv, msg_list);
  1318. X    return;
  1319. X}
  1320. X
  1321. view_opts_menu(event, fd)
  1322. struct inputevent *event;
  1323. X{
  1324. X    static char buf[5];
  1325. X    struct menuitem *m_item;
  1326. X    char *action;
  1327. X    static struct menuitem opts_items[] = {
  1328. X    { MENU_IMAGESTRING,  "Save Options",    O_SAVE  },
  1329. X    { MENU_IMAGESTRING,  "Restore Options",    O_RSTR  },
  1330. X    { MENU_IMAGESTRING,  "Quit Options",    O_QUIT  },
  1331. X    { MENU_IMAGESTRING,  "Help",        MENU_HELP  }
  1332. X    };
  1333. X    static struct menu msgs_menu = {
  1334. X        MENU_IMAGESTRING, "Options", 4, opts_items, (struct menu *)NULL, NULL
  1335. X    };
  1336. X    struct menu *menu_ptr = &msgs_menu;
  1337. X
  1338. X    if (m_item = menu_display(&menu_ptr, event, fd))
  1339. X    action = m_item->mi_data;
  1340. X    else
  1341. X    return;
  1342. X    switch(action) {
  1343. X    case O_SAVE:
  1344. X        save_opts(0, DUBL_NULL);
  1345. X    when O_RSTR:
  1346. X        init();
  1347. X        if (getting_opts == 1)
  1348. X        view_options();
  1349. X        else
  1350. X        set_fkeys();
  1351. X    when O_QUIT:
  1352. X        do_clear();
  1353. X        unlock_cursors(); /* actually resets msg_win's cursor */
  1354. X        if (isoff(glob_flags, IS_GETTING) && msg_cnt)
  1355. X        if (isoff(msg[current_msg].m_flags, DELETE))
  1356. X            display_msg(current_msg, (long)0);
  1357. X        else
  1358. X            (void) read_mail(NO_ITEM, 0, NO_EVENT);
  1359. X    when MENU_HELP:
  1360. X        (void) help(fd, (getting_opts == 1)? "options": "fkeys", tool_help);
  1361. X    }
  1362. X}
  1363. END_OF_FILE
  1364. if test 13055 -ne `wc -c <'select.c'`; then
  1365.     echo shar: \"'select.c'\" unpacked with wrong size!
  1366. fi
  1367. # end of 'select.c'
  1368. fi
  1369. echo shar: End of archive 6 \(of 14\).
  1370. cp /dev/null ark6isdone
  1371. MISSING=""
  1372. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
  1373.     if test ! -f ark${I}isdone ; then
  1374.     MISSING="${MISSING} ${I}"
  1375.     fi
  1376. done
  1377. if test "${MISSING}" = "" ; then
  1378.     echo You have unpacked all 14 archives.
  1379.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1380. else
  1381.     echo You still need to unpack the following archives:
  1382.     echo "        " ${MISSING}
  1383. fi
  1384. ##  End of shell archive.
  1385. exit 0
  1386.